package com.yhn.registration.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hospital.common.pojo.TRegistration;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 挂号预约Mapper接口（原生 MyBatis）
 */
@Mapper
public interface RegistrationMapper extends BaseMapper<TRegistration> {


    /**
     * 检查患者当天是否已有预约
     */
    int checkPatientDeptDailyLimit(@Param("patientId") Long patientId,
                                   @Param("departmentId") Long departmentId,
                                   @Param("appointmentDate") LocalDateTime appointmentDate);

    /**
     * 获取医生在指定时间段的最大患者数
     */
    Integer getMaxPatientsForTimeSlot(@Param("doctorId") Long doctorId,
                                      @Param("startTime") LocalDateTime startTime,
                                      @Param("endTime") LocalDateTime endTime);

    /**
     * 获取医生在指定时间段的已预约人数（带锁）
     */
    Integer getBookedCountForTimeSlot(@Param("doctorId") Long doctorId,
                                      @Param("startTime") LocalDateTime startTime,
                                      @Param("endTime") LocalDateTime endTime);

    /**
     * 检查医生是否在指定日期有排班
     */
    Integer checkDoctorScheduleExists(@Param("doctorId") Long doctorId,
                                      @Param("startTime") LocalDateTime startTime);
    /**
     * 原子性更新医生排班的已预约人数（+1）
     */
    int incrementCurrentBooked(@Param("doctorId") Long doctorId,
                               @Param("startTime") LocalDateTime startTime);

    /**
     * 获取医生排班的当前已预约人数
     */
    Integer getCurrentBookedCount(@Param("doctorId") Long doctorId,
                                  @Param("startTime") LocalDateTime startTime);

    /**
     * 插入挂号记录（数据库自增主键）
     */
    int insert(TRegistration registration);

    /**
     * 根据患者ID查询挂号记录
     */
    List<TRegistration> queryByPatientId(@Param("patientId") Long patientId);

    /**
     * 医生统计当前-当天预约人数
     */
    Integer getDoctorDailyAppointments(@Param("doctorId") Long doctorId);

    /**
     * 原子性减少医生排班的已预约人数（-1）
     */
    int decrementCurrentBooked(@Param("doctorId") Long doctorId,
                               @Param("startTime") LocalDateTime startTime);

    /**
     * 重置所有排班表的已预约人数为0
     */
    int resetAllCurrentBooked();

    /**
     * 根据实际预约记录重新计算已预约人数
     */
    int recalculateCurrentBooked();

    /**
     * 统计医生进行中与已完成的挂号数量（state in 0,1）
     */
    Integer countDoctorActiveRegistrations(@Param("doctorId") Long doctorId);

    /**
     * 统计医生各状态数量（state: 0进行中,1完成,2取消,3未就诊）
     */
    Map<String, Integer> countDoctorRegistrationsByState(@Param("doctorId") Long doctorId);

    /**
     * 患者按状态统计（state: 0进行中,1完成,2取消,3未就诊）
     */
    Map<String, Integer> countPatientRegistrationsByState(@Param("patientId") Long patientId);

    /**
     * 分页查询患者预约记录
     */
    List<TRegistration> queryPatientRegistrationsByPage(@Param("patientId") Long patientId,
                                                        @Param("state") Integer state,
                                                        @Param("offset") Integer offset,
                                                        @Param("limit") Integer limit);

    /**
     * 统计患者预约记录总数（用于分页）
     */
    Integer countPatientRegistrations(@Param("patientId") Long patientId,
                                      @Param("state") Integer state);

    /**
     * 医生端：按条件查询患者（默认当天），分页
     */
    List<TRegistration> doctorSearchPatients(@Param("doctorId") Long doctorId,
                                             @Param("patientName") String patientName,
                                             @Param("startTime") String startTime,
                                             @Param("endTime") String endTime,
                                             @Param("offset") Integer offset,
                                             @Param("limit") Integer limit);

    /** 统计用于分页 */
    Integer countDoctorSearchPatients(@Param("doctorId") Long doctorId,
                                      @Param("patientName") String patientName,
                                      @Param("startTime") String startTime,
                                      @Param("endTime") String endTime);

    /**
     * 医生查询今日所有患者（按预约时间升序，排除已取消）
     */
    java.util.List<com.hospital.common.pojo.TRegistration> doctorListTodayPatients(@Param("doctorId") Long doctorId);



    /**
     * 医生查询所有患者（按预约时间降序，排除已取消）
     */
    java.util.List<com.hospital.common.pojo.TRegistration> doctorListAllPatients(@Param("doctorId") Long doctorId);

    /**
     * 后台管理 - 分页查询所有预约记录（支持多条件查询）
     */
    List<TRegistration> queryAllRegistrationsByPage(@Param("patientName") String patientName,
                                                    @Param("doctorName") String doctorName,
                                                    @Param("department") String department,
                                                    @Param("state") Integer state,
                                                    @Param("startTime") String startTime,
                                                    @Param("endTime") String endTime,
                                                    @Param("offset") Integer offset,
                                                    @Param("limit") Integer limit);

    /**
     * 后台管理 - 统计所有预约记录总数（用于分页）
     */
    Integer countAllRegistrations(@Param("patientName") String patientName,
                                  @Param("doctorName") String doctorName,
                                  @Param("department") String department,
                                  @Param("state") Integer state,
                                  @Param("startTime") String startTime,
                                  @Param("endTime") String endTime);

    /**
     * 后台管理 - 获取预约统计信息
     */
    Map<String, Object> getRegistrationStats();

    /**
     * 后台管理 - 根据ID查询预约详情
     */
    TRegistration getRegistrationById(@Param("id") Long id);

    /**
     * 统计当日预约总数（按预约开始时间所在日期）
     */
    Integer countTodayAppointments();
}
